﻿using System.Linq;
using System.Windows;
using System.Windows.Controls;
using ServerExplorer.SharePointConnections.SharepointSiteInfo;
using System.IO;
using System;
using System.Windows.Data;
using System.Xml;
using System.Collections.Generic;
using System.Windows.Input;
using ServerExplorer.SharePointConnections.SharepointSiteInfo.Entities;
using System.Xml.Serialization;
using System.Threading;
using System.ComponentModel;
using System.Windows.Threading;

namespace Microsoft.SharepointSnifferPackage
{

    public class EventHandlersParameters
    {
        public ManualResetEvent eventReset;
        public MyControl control;
    }

    public delegate void SetText(string text);

    public delegate void NextHandler(Object obj);

    /// <summary>
    /// Interaction logic for MyControl.xaml
    /// </summary>
    public partial class MyControl : UserControl
    {
        public XmlDataProvider MyControlDataProvider { get; set; }

        private delegate void ControlDispatcher(object text);

        private Cursor c;

        public SetText TextT1;

        long starTime;

        public static ManualResetEvent handlersEvent = new ManualResetEvent(false);

        public MyControl()
        {
            InitializeComponent();
            T1.Text = string.Empty;
            MyControlDataProvider = FindResource("siteinfo") as XmlDataProvider;
            TextT1 = this.TextWrite;
        }

        private void setButton(object enable)
        {
            if (this.Dispatcher.CheckAccess())
            {
                this.button1.IsEnabled = (Boolean)enable;
            }
            else
            {
                this.Dispatcher.Invoke(
                    System.Windows.Threading.DispatcherPriority.Normal,
                    new ControlDispatcher(this.setButton), enable);
            }
        }

        private void setCursor(object cur)
        {
            if (this.Dispatcher.CheckAccess())
            {
                this.Cursor = (Cursor)cur;
            }
            else
            {
                this.Dispatcher.Invoke(
                    System.Windows.Threading.DispatcherPriority.Normal,
                    new ControlDispatcher(this.setCursor), cur);
            }
        }


        private void setTreeView(object doc)
        {
            if (this.treeview.Dispatcher.CheckAccess())
            {
                treeview.ItemsSource = (XmlDocument)doc;
                if (doc == null)
                {
                    treeview.Items.Clear();
                }
            }
            else
            {
                this.treeview.Dispatcher.Invoke(
                    System.Windows.Threading.DispatcherPriority.Normal,
                    new ControlDispatcher(this.setTreeView), doc);
            }
        }

        private void ShowData(Object obj)
        {
            MountXmlDataProvider(Access.SiteStructInfo, MyControlDataProvider);
            setTreeView(MyControlDataProvider.Document);
            InsertText(String.Format("{0}({1})", "Fim do Processamento", new DateTime(DateTime.Now.Ticks - starTime).ToString("HH:mm:ss.ffff")));
            Access.XmlView("Struct_" + DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss"), MyControlDataProvider.Document.InnerXml);
            ((ManualResetEvent)obj).Set();
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions")]
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            if (Access.conn != null)
            {
                starTime = DateTime.Now.Ticks;
                setButton(false);
                //Setting HourGlass Cursor
                c = this.Cursor;
                setCursor(Cursors.Wait);
                setTreeView(null);
                InsertText("Em processamento...");
                Thread md = new Thread(Handlers);
                md.Start(this);
            }
            else
            {
                MessageBox.Show("Definir Conexão");
            }
        }

        private void Handlers(Object obj)
        {
            MountDataStruct((Object)handlersEvent);

            handlersEvent.WaitOne();

            handlersEvent.Reset();

            ShowData((Object)handlersEvent);

            handlersEvent.WaitOne();
            setCursor(c);
            setButton(true);
        }

        private void TextWrite(string text)
        {
            Thread log = new Thread(InsertText);
            log.Start((object)text);
        }

        public void InsertText(object text)
        {
            if (this.T1.Dispatcher.CheckAccess())
            {
                this.T1.Text = (string)text;
                this.T1.Refresh();
            }
            else
            {
                this.T1.Dispatcher.Invoke(
                    System.Windows.Threading.DispatcherPriority.Normal,
                    new ControlDispatcher(this.InsertText), text);
            }
        }

        private void MountDataStruct(Object obj)
        {
            //Get RootWeb and Subsites
            Access.SiteStructInfo = Access.conn.ExecuteCommand<SiteStructInfo>(SharepointSiteInfoCommandsIDs.GetSharepointSiteRootInfo);

            //Get Files and Subfolders
            List<Web> auxWeb = new List<Web>();
            int position = 0;
            auxWeb.Add(Access.SiteStructInfo.RootWeb);

            //Auxiliar WebPart List
            Access.AllWebParts = new List<WebPartInfo>();
            ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            while (position < auxWeb.Count)
            {
                Web w = auxWeb[position++];
                InsertText("Processando estrutura de Diretorios");

                if (w.SubSites.Webs.Count > 0)
                {
                    auxWeb.AddRange(w.SubSites.Webs);
                }

                ProcessFolderFiles processFolderFiles = new ProcessFolderFiles(w.Guid, w.Folders, w.Pages, manualResetEvent, this);
                ThreadPool.QueueUserWorkItem(processFolderFiles.ThreadPoolCallback);
            }

            if (position > 0)
            {
                InsertText("Aguardando fim do processamento estrutura de Diretorios e Arquivos");

                manualResetEvent.WaitOne();

                //Processing WebPartInfo
                InsertText("Processando estrutura de WebParts");
                mappingWebParts(Access.AllWebParts);
            }

            ((ManualResetEvent)obj).Set();
        }

        private void mappingWebParts(List<WebPartInfo> AllWebParts)
        {

            List<string> webPartTypes = AllWebParts.Select(s => string.Format("{0};{1}", s.WebPartType, s.Open)).Distinct().ToList();
            webPartTypes.Sort();
            foreach (string wbType in webPartTypes)
            {
                WebPartStruct wpStruct = new WebPartStruct();
                string[] data = wbType.Split(';');
                wpStruct.WebPartName = data[0];
                wpStruct.Page.AddRange(AllWebParts.Where(w => w.WebPartType.Equals(data[0])).Select(s => (WebPartPage)string.Format("{0};{1}", s.Page, data[1])));
                Access.SiteStructInfo.WebPartsAllocation.WebPartStructs.Add(wpStruct);
            }
        }

        private void MountXmlDataProvider(Object source, XmlDataProvider dp)
        {
            var xmlDocument = new XmlDocument();
            using (MemoryStream m = new MemoryStream())
            {
                XmlSerializer x = new System.Xml.Serialization.XmlSerializer(source.GetType());
                XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
                namespaces.Add(string.Empty, string.Empty);
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.OmitXmlDeclaration = true;
                using (XmlWriter stringWriter = XmlWriter.Create(m, settings))
                {
                    x.Serialize(stringWriter, source, namespaces);
                }
                m.Position = 0;
                xmlDocument.Load(m);
            }
            dp.Document = xmlDocument;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions")]
        private void fopen_Click(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.OpenFileDialog fd = new System.Windows.Forms.OpenFileDialog();
            if (fd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(fd.FileName);
                MyControlDataProvider.Document = xmlDoc;
                setTreeView(MyControlDataProvider.Document);
                InsertText(String.Format("{0}:{1}", "Arquivo Importado", fd.FileName));
            }
        }
    }
}